package com.example.niu.qqapp

import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.niu.qqapp.databinding.ActivityChatBinding
import com.google.android.material.snackbar.Snackbar
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Action
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
import kotlin.collections.ArrayList

class ChatActivity : AppCompatActivity() {

    //新式view binding，整天TM改来改去！
    private lateinit var binding: ActivityChatBinding

    //用于网络通讯
    private lateinit var retrofit: Retrofit
    private lateinit var chatService: ChatService

    private var uploadDisposable : Disposable? = null
    private var downloadDisposable : Disposable? = null

    //存放所有的聊天消息
    private val chatMessages = ArrayList<Message>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityChatBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //创建Retrofit对象
        retrofit = Retrofit.Builder()
            //.baseUrl("http://10.0.2.2:8080/")
            .baseUrl("http://10.0.2.2:8080")//在我的手机中运行
            //本来接口方法返回的是Call，由于现在返回类型变成了Observable，
            //所以必须设置Call适配器将Observable与Call结合起来
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            //Json数据自动转换
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        //创建网络通讯服务对象
        chatService = retrofit.create(ChatService::class.java)

        //获取启动此Activity时传过来的数据
        //在启动聊天界面时，通过此方式把对方的名字传过来
        val contactName= intent.getStringExtra("contact_name")
        //设置动作栏标题
        binding.toolbar.title = contactName

        setSupportActionBar(binding.toolbar)
        //设置显示动作栏上的返回图标
        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        //为RecyclerView设置适配器
        binding.chatMessageListView.layoutManager = LinearLayoutManager(this)
        binding.chatMessageListView.adapter = ChatMessagesAdapter()

        //响应按钮的点击，发出消息
        binding.buttonSend.setOnClickListener {
            //从EditText控件取得消息
            val msg = binding.editMessage.text.toString()

            //创建消息对象，准备上传
            val chatMessage = Message(MainActivity.myInfo!!.name, java.util.Date().time, msg)

            //上传到服务端
            val observable = chatService.uploadMessage(chatMessage)
            observable.retry().map{
                //判断服务端是否正确返回
                if (it.retCode == 0) {
                    //服务端无错误，随便返回点东西吧，反正也不用处理
                    0
                } else {
                    //服务端出错了，抛出异常，在Observer中捕获之
                    throw RuntimeException(it.errMsg)
                }
            }.subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                //范型参数之所以是Int，是因为必须与map的回调函数返回的数据类型一致
                Consumer<Int>{
                    //对应onNext()，但是什么也不需要做
                },
                Consumer<Throwable> {
                    //对应onError()，向用户提示错误
                    Snackbar.make(binding.chatMessageListView,
                        "大王祸事了：" + it.localizedMessage,
                        Snackbar.LENGTH_LONG)
                        .setAction("Action", null)
                        .show()
                },
                Action() {
                    //对应onComplete()，什么也不做
                },
                Consumer<Disposable> {
                    //相当于onSubcribe()，保存下disposable以取消订阅
                    uploadDisposable = it
                }
            )

            //添加到集合中，从而能在RecyclerView中显示
            chatMessages.add(chatMessage);
            //在view中显示出来。通知RecyclerView，更新一行
            (binding.chatMessageListView.adapter as ChatMessagesAdapter).notifyItemInserted(chatMessages.size - 1)
            //让RecyclerView向下滚动，以显示最新的消息
            binding.chatMessageListView.scrollToPosition(chatMessages.size - 1)
        }

        //每隔2秒向服务端获取一下新的聊天消息
        Observable.interval(2, TimeUnit.SECONDS).flatMap{
            //创建获取聊天消息的Observable
            //参数是下一坨Message的起始Index
            chatService.getMessagesFromIndex(chatMessages.size)
                .map {                    //判断服务端是否正确返回
                    if (it.retCode === 0) {
                        //服务端无错误，随便返回点东西吧，反正也不用处理
                        it.data
                    } else {
                        //服务端出错了，抛出异常，在Observer中捕获之
                        throw RuntimeException(it.errMsg)
                    }
                }
        }.retry()
            .subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(Consumer<List<Message>?> {
                //onNext()
                // 将消息显示在RecyclerView中,it是 List<Message>?
                chatMessages.addAll(it!!)
                //在view中显示出来。通知RecyclerView，更新一行
                binding.chatMessageListView.adapter!!.notifyItemRangeInserted(
                    chatMessages.size, chatMessages.size)
                //让RecyclerView向下滚动，以显示最新的消息
                binding.chatMessageListView.scrollToPosition(chatMessages.size - 1)
            }, Consumer<Throwable> { e ->
                //onError()
                // 反正要重试，什么也不做了
                Log.e("chatactivity", e.localizedMessage)
            }, Action { //onComplete()

            }, Consumer<Disposable> { disposable ->
                    //onSubcribe()
                    //保存下downloadDisposable以取消订阅
                    downloadDisposable = disposable
            })
    }

    override fun onOptionsItemSelected(item : MenuItem) : Boolean {
        if (item.itemId == android.R.id.home) {
            //当点击动作栏上的返回图标时执行
            //关闭自己，返回来时的页面
            finish();
        }
        return super.onOptionsItemSelected(item);
    }

    override fun onDestroy() {
        super.onDestroy()
        uploadDisposable?.let {
            it.dispose()
            uploadDisposable = null
        }

        downloadDisposable?.let {
            it.dispose()
            downloadDisposable = null
        }
    }
    //为RecyclerView提供数据的适配器
    inner class ChatMessagesAdapter : RecyclerView.Adapter<ChatMessagesAdapter.MyViewHolder>() {
        override fun onCreateViewHolder(parent:ViewGroup, viewType:Int): MyViewHolder {
            //参数viewType即行的Layout资源Id，由getItemViewType()的返回值决定的
            val itemView =  layoutInflater.inflate(viewType,parent,false);
            return MyViewHolder(itemView);
        }

        override fun onBindViewHolder(holder:MyViewHolder, position:Int) {
            val message = chatMessages[position];
            holder.textView.setText(message.content);
        }

        override fun getItemCount():Int{
            return chatMessages.size;
        }

        //有两种行layout，所以Override此方法
        override fun getItemViewType(position:Int):Int{
            val message = chatMessages[position];
            return if(message.contactName == MainActivity.myInfo!!.name) {
                //如果是我的，靠右显示
                R.layout.chat_message_right_item;
            }else{
                //对方的，靠左显示
                R.layout.chat_message_left_item;
            }
        }

        inner class MyViewHolder(itemView:View): RecyclerView.ViewHolder(itemView){
            val textView = itemView.findViewById(R.id.textView) as TextView
            val ImageView = itemView.findViewById(R.id.imageView) as ImageView
        }
    }
}
